﻿using CristoRessuscitado.BancoDados;
using CristoRessuscitado.Utils;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CristoRessuscitado.Formularios
{
    public partial class FormCadPessoa : Form, IFormCadPadrao
    {
        private const int             CB_SEXO_INDEX_MASCULINO = 0;
        private const int             CB_SEXO_INDEX_FEMININO  = 1;

        private const int             CB_UF_INDEX_SP          = 24;

        public        bool            FlagAlteracao           { get; set; }
        public        int             IdRegistro              { get; set; }

        private       DatabaseContext dbContext;
        private       Pessoa          pessoa;

        public FormCadPessoa()
        {
            InitializeComponent();
        }

        // ---------------------------------------------------------------------------------------------------------------------------
        //
        // Eventos
        //
        // ---------------------------------------------------------------------------------------------------------------------------

        private void FormCadPessoa_Load(object sender, EventArgs e)
        {
            Inicializar();
        }

        private void FormCadPessoa_KeyDown(object sender, KeyEventArgs e)
        {
            OnTecladoKeyDown(e);
        }

        private void btnSalvar_Click(object sender, EventArgs e)
        {
            if (Validar())
            {
                Salvar();
                Close();
            }
        }

        private void btnAdicionarFuncaoPessoa_Click(object sender, EventArgs e)
        {
            AdicionarFuncaoInformadaNaComboBoxNaListaBox();
        }

        private void btnExcluirFuncaoPessoa_Click(object sender, EventArgs e)
        {
            RemoverFuncaoSelecionadaListBox();
        }

        // ---------------------------------------------------------------------------------------------------------------------------
        //                                                                                                                           
        // Métodos Auxiliares                                                                                                        
        //                                                                                                                           
        // ---------------------------------------------------------------------------------------------------------------------------

        public void OnTecladoKeyDown(KeyEventArgs e)
        {
            if (e.KeyCode == (Keys.Escape))
            {
                Close();
            }
        }

        public void Inicializar()
        {
            dbContext = new DatabaseContext();
            KeyPreview = true;

            ConfigurarDateTimePickerNascimento();
            ConfigurarComboBoxSexo();
            ConfigurarComboBoxFuncoes();
            ConfigurarListBoxFuncoes();

            if (!FlagAlteracao)
            {
                Text = MensagensPadrao.titulo_incluir_novo_registro;

                pessoa = new Pessoa();

                PopularCamposParaInclusao();
            }
            else
            {
                Text = MensagensPadrao.titulo_alterar_registro;

                pessoa = dbContext.Pessoa.Find(IdRegistro);

                PopularCamposParaAlteracao();
            }
        }

        public void PopularCamposParaInclusao()
        {
            cbSexo.SelectedIndex = CB_SEXO_INDEX_MASCULINO;
            cbUF.SelectedIndex = CB_UF_INDEX_SP;
        }

        public void PopularCamposParaAlteracao()
        {
            tbNome.Text = pessoa.NomeCompleto;
            string sexo = pessoa.Sexo;
            if (sexo == "M")
                cbSexo.SelectedIndex = CB_SEXO_INDEX_MASCULINO;
            else
                cbSexo.SelectedIndex = CB_SEXO_INDEX_FEMININO;
            dtpDataNascimento.Value = pessoa.DataNascimento.Value;
            cbUF.SelectedItem = pessoa.UF;
            tbCidade.Text = pessoa.Cidade;
            tbEndereco.Text = pessoa.Endereco;
            tbEmail.Text = pessoa.Email;
            tbFacebook.Text = pessoa.Facebook;
            mtbTelefoneResidencial.Text = pessoa.TelefoneResidencial;
            mtbTelefoneCelular.Text = pessoa.TelefoneCelular;
            AlimentarListBoxComAsFuncoesDaPessoa();
        }

        public bool Validar()
        {
            string nome = tbNome.Text.Trim();
            if (string.IsNullOrEmpty(nome))
            {
                GeralUtils.ExibirDialogMsgValidacao(this, "Informe o nome.");
                tbNome.Focus();
                return false;
            }
            else
            {
                if (nome.Length < 1 || nome.Length > 300)
                {
                    GeralUtils.ExibirDialogMsgValidacao(this, "Informe o nome com tamanho entre 1 e 300 caracteres.");
                    tbNome.Focus();
                    return false;
                }
            }

            if (dtpDataNascimento.Value > DateTime.Now)
            {
                GeralUtils.ExibirDialogMsgValidacao(this, "A data de nascimento não pode ser maior que a data corrente.");
                dtpDataNascimento.Focus();
                return false;
            }

            string cidade = tbCidade.Text.Trim();
            if (string.IsNullOrEmpty(cidade))
            {
                GeralUtils.ExibirDialogMsgValidacao(this, "Informe a cidade.");
                tbCidade.Focus();
                return false;
            }
            else
            {
                if (cidade.Length < 1 || cidade.Length > 150)
                {
                    GeralUtils.ExibirDialogMsgValidacao(this, "Informe a cidade com tamanho entre 1 e 150 caracteres.");
                    tbCidade.Focus();
                    return false;
                }
            }

            string endereco = tbEndereco.Text.Trim();
            if (!string.IsNullOrEmpty(endereco))
            {
                if (endereco.Length < 1 || endereco.Length > 500)
                {
                    GeralUtils.ExibirDialogMsgValidacao(this, "Informe o endereço com tamanho entre 1 e 500 caracteres.");
                    tbEndereco.Focus();
                    return false;
                }
            }

            string email = tbEmail.Text.Trim();
            if (!string.IsNullOrEmpty(email))
            {
                if (email.Length < 1 || email.Length > 150)
                {
                    GeralUtils.ExibirDialogMsgValidacao(this, "Informe o e-mail com tamanho entre 1 e 150 caracteres.");
                    tbEmail.Focus();
                    return false;
                }
            }

            string facebook = tbFacebook.Text.Trim();
            if (!string.IsNullOrEmpty(facebook))
            {
                if (facebook.Length < 1 || facebook.Length > 300)
                {
                    GeralUtils.ExibirDialogMsgValidacao(this, "Informe o endereço do facebook com tamanho entre 1 e 300 caracteres.");
                    tbFacebook.Focus();
                    return false;
                }
            }

            string telResidencial = mtbTelefoneResidencial.Text.Trim();
            if (!string.IsNullOrEmpty(telResidencial))
            {
                if (!mtbTelefoneResidencial.MaskCompleted)
                {
                    GeralUtils.ExibirDialogMsgValidacao(this, "Informe o telefone corretamente.");
                    mtbTelefoneResidencial.Focus();
                    return false;
                }
            }

            string telCelular = mtbTelefoneCelular.Text.Trim();
            if (!string.IsNullOrEmpty(telCelular))
            {
                if (!mtbTelefoneCelular.MaskCompleted)
                {
                    GeralUtils.ExibirDialogMsgValidacao(this, "Informe o celular corretamente.");
                    mtbTelefoneCelular.Focus();
                    return false;
                }
            }

            return true;
        }

        // TODO Encapsular Queries
        public void Salvar()
        {
            /** 
             * Transação responsável por salvar/editar uma pessoa no banco de dados 
             * 
             **/
            var transacao = dbContext.Database.BeginTransaction();
            try
            {
                int idPessoa;
                PopularEntidadePessoaComValoresGeraisFormulario();

                if (!FlagAlteracao)
                {
                    Pessoa pessoaInserida = dbContext.Pessoa.Add(pessoa);
                    dbContext.SaveChanges();

                    idPessoa = pessoaInserida.IdPessoa;
                }
                else
                {
                    idPessoa = pessoa.IdPessoa;

                    dbContext.Database.ExecuteSqlCommand("delete from PessoaFuncao where IdPessoa = @IdPessoa",
                                                            new SqlParameter("@IdPessoa", idPessoa));
                }

                IEnumerable<Funcao> itensListBoxFuncoes = listBoxFuncoes.Items.Cast<Funcao>();
                foreach (var item in itensListBoxFuncoes)
                {
                    int idFuncao = item.IdFuncao;
                    dbContext.Database.ExecuteSqlCommand("insert into PessoaFuncao (IdPessoa, IdFuncao) values (@IdPessoa, @IdFuncao)",
                                                            new SqlParameter("@IdPessoa", idPessoa), new SqlParameter("@IdFuncao", idFuncao));
                }

                // Sincroniza =>>
                dbContext.SaveChanges();
                transacao.Commit();
            }
            catch (Exception ex)
            {
                transacao.Rollback();
                GeralUtils.ExibirDialogMsgErro(this, MensagensPadrao.txt_geral_ocorreu_erro_inesperado + ex.Message);
            }
        }

        /** No caso deste formulário as regras permitem que esta mesma lógica sirva tanto para Incluir quanto Alterar um registro **/
        private void PopularEntidadePessoaComValoresGeraisFormulario()
        {
            pessoa.NomeCompleto = tbNome.Text.Trim();
            pessoa.DataNascimento = dtpDataNascimento.Value;
            pessoa.UF = cbUF.SelectedItem.ToString();
            pessoa.Cidade = tbCidade.Text.Trim();
            pessoa.Endereco = tbEndereco.Text.Trim();
            pessoa.Sexo = getCharCBSexoSelecionado();
            pessoa.TelefoneCelular = mtbTelefoneCelular.Text.Trim();
            pessoa.TelefoneResidencial = mtbTelefoneResidencial.Text.Trim();
            pessoa.Email = tbEmail.Text.Trim();
            pessoa.Facebook = tbFacebook.Text.Trim();
        }

        private string getCharCBSexoSelecionado()
        {
            string charSexo = "";
            if (cbSexo.SelectedIndex == 0)
                charSexo = "M";
            else
                charSexo = "F";

            return charSexo;
        }

        private void RemoverFuncaoSelecionadaListBox()
        {
            int indexSelecionadoListBoxFuncoes = listBoxFuncoes.SelectedIndex;
            if (!(indexSelecionadoListBoxFuncoes == -1))
            {
                listBoxFuncoes.Items.RemoveAt(listBoxFuncoes.SelectedIndex);
            }
            else
            {
                GeralUtils.ExibirDialogMsgValidacao(this, "Selecione uma função na lista para excluir.");
            }
        }

        private void ConfigurarComboBoxSexo()
        {
            cbSexo.Items.Insert(CB_SEXO_INDEX_MASCULINO, "Masculino");
            cbSexo.Items.Insert(CB_SEXO_INDEX_FEMININO, "Feminino");
        }

        private void AlimentarListBoxComAsFuncoesDaPessoa()
        {
            foreach (var funcao in this.pessoa.Funcao)
            {
                listBoxFuncoes.Items.Add(funcao);
            }
        }

        private void ConfigurarListBoxFuncoes()
        {
            listBoxFuncoes.ValueMember = VarConUtils.LIST_FUNCAO_VALUE_MEMBER;
            listBoxFuncoes.DisplayMember = VarConUtils.LIST_FUNCAO_DISPLAY_MEMBER;
        }

        private void ConfigurarComboBoxFuncoes()
        {
            var funcoes = dbContext.Funcao.OrderBy(e => e.Nome).ToList();

            cbFuncoes.ValueMember = VarConUtils.LIST_FUNCAO_VALUE_MEMBER;
            cbFuncoes.DisplayMember = VarConUtils.LIST_FUNCAO_DISPLAY_MEMBER;
            cbFuncoes.DataSource = funcoes;
        }

        private void ConfigurarDateTimePickerNascimento()
        {
            dtpDataNascimento.Format = DateTimePickerFormat.Custom;
            dtpDataNascimento.CustomFormat = VarConUtils.FORMATO_DATA_A;
        }

        private void AdicionarFuncaoInformadaNaComboBoxNaListaBox()
        {
            Funcao itemSelecionadoCB = (Funcao)cbFuncoes.SelectedItem;

            if (itemSelecionadoCB != null)
            {
                IEnumerable<Funcao> itensListBox = listBoxFuncoes.Items.Cast<Funcao>();

                bool existeItemNaListBox = itensListBox.Any(m => m.IdFuncao == itemSelecionadoCB.IdFuncao);
                if (!existeItemNaListBox)
                {
                    listBoxFuncoes.Items.Insert(0, itemSelecionadoCB);
                }
                else
                {
                    GeralUtils.ExibirDialogMsgValidacao(this, "A pessoa já está associada a esta função. Por favor, escolha outra.");
                }
            }
        }
    }
}